package com.sky.utils;

import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
import java.util.regex.Pattern;

/**
 * MinIO 文件上传工具类
 */
@Data
@AllArgsConstructor
@Slf4j
public class MinioUtil {

    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String bucketName;

    // S3存储桶名称验证正则表达式
    private static final Pattern BUCKET_NAME_PATTERN =
            Pattern.compile("^[a-z0-9]([a-z0-9\\-]{0,61}[a-z0-9])?$");

    /**
     * 文件上传
     *
     * @param bytes
     * @param objectName
     * @return
     */
    public String upload(byte[] bytes, String objectName) {
        // 创建 MinIO 客户端
        MinioClient minioClient = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();

        try {
            // 验证并修正存储桶名称
            String validBucketName = validateAndFixBucketName(bucketName);

            // 检查存储桶是否存在，不存在则创建
            boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder()
                    .bucket(validBucketName)
                    .build());

            if (!bucketExists) {
                minioClient.makeBucket(MakeBucketArgs.builder()
                        .bucket(validBucketName)
                        .build());
            }

            // 上传文件
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(validBucketName)
                    .object(objectName)
                    .stream(new ByteArrayInputStream(bytes), bytes.length, -1)
                    .build());

            // 更新存储桶名称为修正后的名称
            this.bucketName = validBucketName;

        } catch (Exception e) {
            log.error("MinIO 文件上传失败: {}", e.getMessage(), e);
            throw new RuntimeException("文件上传失败", e);
        }

        // 文件访问路径规则 https://Endpoint/BucketName/ObjectName
        StringBuilder stringBuilder = new StringBuilder();

        // 如果是 HTTP 协议，需要添加协议头
        if (!endpoint.startsWith("http")) {
            stringBuilder.append("https://");
        }

        stringBuilder
                .append(endpoint)
                .append("/")
                .append(bucketName)
                .append("/")
                .append(objectName);

        log.info("文件上传到: {}", stringBuilder.toString());
        return stringBuilder.toString();
    }

    /**
     * 验证并修正存储桶名称，确保符合 S3 标准
     */
    private String validateAndFixBucketName(String originalName) {
        // 检查是否符合 S3 存储桶命名规范
        if (BUCKET_NAME_PATTERN.matcher(originalName).matches()) {
            return originalName;
        }

        log.warn("存储桶名称 '{}' 不符合 S3 标准，正在尝试修正...", originalName);

        // 转换为小写
        String sanitizedName = originalName.toLowerCase();

        // 替换非法字符为连字符
        sanitizedName = sanitizedName.replaceAll("[^a-z0-9-]", "-");

        // 移除连续的连字符
        sanitizedName = sanitizedName.replaceAll("-+", "-");

        // 确保不以连字符开头或结尾
        if (sanitizedName.startsWith("-")) {
            sanitizedName = sanitizedName.substring(1);
        }
        if (sanitizedName.endsWith("-")) {
            sanitizedName = sanitizedName.substring(0, sanitizedName.length() - 1);
        }

        // 截断到最大长度
        if (sanitizedName.length() > 63) {
            sanitizedName = sanitizedName.substring(0, 63);
        }

        // 如果处理后名称为空，生成随机名称
        if (sanitizedName.isEmpty()) {
            sanitizedName = "bucket-" + System.currentTimeMillis();
        }

        // 确保名称以字母或数字开头
        if (!Character.isLetterOrDigit(sanitizedName.charAt(0))) {
            sanitizedName = "b-" + sanitizedName;
        }

        log.info("修正后的存储桶名称: {}", sanitizedName);
        return sanitizedName;
    }
}